package com.zh.demo;

import com.fasterxml.jackson.databind.json.JsonMapper;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import technology.tabula.*;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 利用tabula 解析pdf中的表格
 */
public class PdfUtils {

    // 表格提取算法
    SpreadsheetExtractionAlgorithm sa = new SpreadsheetExtractionAlgorithm();

    JsonMapper mapper = new JsonMapper();

    private static final String KEY_MONTH_STATEMENT = "monthStatement";

    private static final String KEY_PASSAGE_DETAIL = "passageDetail";

    private static final String KEY_PARK_DETAIL = "parkDetail";


    public static void main(String[] args) {

        File file = new File("C:\\Users\\zhjx2\\Documents\\卡号1_停车记录有边框.pdf");
        PdfUtils pdfUtils = new PdfUtils();
//        pdfUtils.readTableDataFromPdf(file);
//        String txt = pdfUtils.readTxtFromPdf( file);
//        System.out.println(txt);
        pdfUtils.readTableFromPdf(file);


    }



    /**
     * 读取pdf中表格信息
     * 主要解决两个问题
     * 1. 识别出文件中的表格
     * 2. 识别出在同一个页码的两个表格不是或者不在同一个页中的两个表格是否为同一个表格
     * @param file
     * @return
     */
    public void readTableFromPdf(File file){

        try {
            // 加载pdf文件
            PDDocument document = PDDocument.load(file);
            ObjectExtractor extractor = new ObjectExtractor(document);

            // 提取pdf中page
            PageIterator pages = extractor.extract();

            int pageNum = 0;

            int pageCount = document.getNumberOfPages();

            int tableNo = 0;

            List<Map<String,String>> tableDataList = new ArrayList<>();  // 记录表中所有数据

            TableFeature previousTableFeature = null;   // 标记上一个table对象特征

            while (pages.hasNext()) {
                Page page = pages.next();
                pageNum = page.getPageNumber();
                List<Table> tableList = sa.extract(page);

                for (int tableIndex = 0; tableIndex < tableList.size(); tableIndex++) {
                    System.out.println(String.format("读取%s页中的第%s表格", pageNum, tableIndex));
                    Table curTable = tableList.get(tableIndex);

                    if (page.getPageNumber() == 1 && tableIndex == 0) {
                        // 读取月结单 表
                        readMethodlyStatement(curTable);
                        previousTableFeature = TableFeature.create(curTable, page.getPageNumber());
                    } else {
                        // 读取 passages 中 表
                        List<Map<String, String>> data = readTableDataFromPdf(curTable);
                        TableFeature currentTableFeature = TableFeature.create(curTable, page.getPageNumber());
                        // 判断当前table对象特征是否和上一个table对象特征一致
                        if (previousTableFeature != null && previousTableFeature.compareTo(currentTableFeature)) {
                            System.out.println(String.format("%s表格未读完", tableNo));
                            // 当前table对象和上一个table对象特征一致,将两个表格数据合并
                            tableDataList.addAll(data);
                        } else {
                            System.out.println(mapper.writeValueAsString(tableDataList));
                            System.out.println("表格" + tableNo + "读取完成--------------");
                            tableNo = tableNo + 1;
                            previousTableFeature = currentTableFeature;
                            tableDataList.clear();
                            System.out.println(String.format("开始读取%s个表", tableNo));
                            tableDataList.addAll(data);
                        }
                    }
                }

                // 输出最后一个表格信息
                if (page.getPageNumber() == pageCount){
                    // 输出表格信息
                    System.out.println(mapper.writeValueAsString(tableDataList));
                }

            }

            extractor.close();
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     * 解析月结单表格
     * @param table
     */
    public void readMethodlyStatement(Table  table){

        int rowCount = 0;
        for (List<RectangularTextContainer> row: table.getRows()){
//            System.out.println("row:"+rowCount++);
            for (RectangularTextContainer cell: row){
                List<RectangularTextContainer> textElements = cell.getTextElements();
                if (textElements.size()>1) {
                    StringBuffer text = new StringBuffer();
                    for(RectangularTextContainer textElement: textElements){
                        text.append(textElement.getText(false));
                    }
//                    System.out.println(text.toString());
                }else{
//                    System.out.println(cell.getText(false) + " ");
                }
            }
//            System.out.println("--------------");
        }
        System.out.println("月结单读完");

    }



    /**
     * 读取pdf中每个单元格都有边框的表格
     * https://gitee.com/cxy_meteor/boot-business/blob/master/boot-business-pdf/src/main/java/com/qiangesoft/pdf/util/PdfUtil.java
     * @param file
     * @return
     */
    public List<Detail> readMonthly(File file){
        List<Detail> details = null;
        try {
            // 加载pdf文件
            PDDocument document = PDDocument.load( file); //PDDocument.load(file);
            ObjectExtractor extractor = new ObjectExtractor(document);

            // 提取pdf中page
            PageIterator pages = extractor.extract();

            details = new ArrayList<>();
            while (pages.hasNext()) {

                Page page = pages.next();
                List<Table> tables = sa.extract( page);

                System.out.println("表格数量：" + tables.size());
                // 获取page中表格
                for (Table table : tables){

                    // 获取表格中行
                    List<List<RectangularTextContainer>> rowList = table.getRows();
                    for (int rowIndex = 0; rowIndex < rowList.size(); rowIndex++){
                        Detail detail = new Detail();
                        if (rowIndex == 0){
                            continue;
                        }
                        // 解析表格中列
                        List<RectangularTextContainer> row = rowList.get(rowIndex);

                        detail.setIndex(row.get(0).getText(true));
                        detail.setCardId(row.get(1).getText(true));
                        detail.setCarNo(row.get(2).getText(true));
                        detail.setTransTime(row.get(3).getText(true));
                        detail.setTransArea(row.get(4).getText(true));
//                        detail.setTransAmount(row.get(5).getText(true));
//                        detail.setDeductionAmount(row.get(6).getText(true));
//                        detail.setRecordTime(row.get(7).getText(true));

                        details.add(detail);
                    }
                }

            }
//            System.out.println(mapper.writeValueAsString( details));
            for (Detail detail : details){
                System.out.println(mapper.writeValueAsString( detail));
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
        return details;
    }


    /**
     * 读取pdf表格数据
     * @param table
     * @return
     */
    public List<Map<String,String>> readTableDataFromPdf(Table  table){
        List<Map<String,String>> dataList = new ArrayList<>();
        for (List<RectangularTextContainer> row: table.getRows()){
            Map<String,String> data = new HashMap<>();
            String key = row.get(0).getText(false);
            StringBuffer rowValue = new StringBuffer();
            for (RectangularTextContainer cell: row){
                List<RectangularTextContainer> textElements = cell.getTextElements();
                if (textElements.size()>1) {
                    StringBuffer text = new StringBuffer();
                    for(RectangularTextContainer textElement: textElements){
                        text.append(textElement.getText(false));
                    }
//                    System.out.println(text.toString());
                    rowValue.append(text.toString()+" ; ");
                }else{
//                    System.out.println(cell.getText(false) + " ");
                    rowValue.append(cell.getText(false)+" ; ");
                }
            }
            data.put(key,rowValue.toString());
            dataList.add(data);
        }

        return dataList;
    }




    //https://blog.csdn.net/weixin_39311781/article/details/148280313



    /**
     * 读取pdf中纯文本
     * @param file
     * @return
     */
    public String readTxtFromPdf(File file){
        String textContent = "";
        try (PDDocument document = PDDocument.load(file)) {
            PDFTextStripper stripper = new PDFTextStripper();
            textContent = stripper.getText(document);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return textContent;
    }


    /**
     * 读取指定文字中间的文本
     *
     * @param txt 文本
     * @param startStr 开始字符串
     * @param endStr 结束字符串
     * @return
     */
    public static String readTxtFormTxt(String txt, String startStr, String endStr) {
        int index1 = txt.indexOf(startStr);
        if (index1 == -1) {
            return null;
        }
        int index2 = txt.length();
        if (endStr != null) {
            index2 = txt.indexOf(endStr);
            if (index2 == -1) {
                index2 = txt.length();
            }
        }

        return txt.substring(index1 + startStr.length(), index2);
    }

}
